/*
给定两个单词（beginWord 和 endWord）和一个字典，找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则：

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:

如果不存在这样的转换序列，返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的，且二者不相同。
示例 1:

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

输出: 5

解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
     返回它的长度 5。
示例 2:

输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

输出: 0

解释: endWord "cog" 不在字典中，所以无法进行转换。

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/word-ladder
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
*/
/*
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        queue<string> bfs;
        bfs.push(beginWord);
        unordered_set<string> visited;
        int len=0;
        int bfs_len=0;
        string tmp;
        while(!bfs.empty()){
            len++;
            bfs_len=bfs.size();
            for(int i=0;i<bfs_len;i++){
                tmp=bfs.front();
                bfs.pop();
                for(int j=0;j<wordList.size();j++){
                    if(onediff(tmp,wordList[j])&&visited.find(wordList[j])==visited.end()){
                        bfs.push(wordList[j]);
                        visited.insert(wordList[j]);
                        if(wordList[j]==endWord){
                            return len+1;
                        }
                    }
                }
            }
        }
        return 0;
    }
private:
    bool onediff(const string a,const string b){
        int len=a.size();
        int diff=0;
        for(int i=0;i<len;i++){
            if(a[i]!=b[i]){
                diff++;
                if(diff==2){
                    return false;
                }
            }
        }
        return true;
    } 
};
*/
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        queue<int> bfs;
        auto itor=find(wordList.begin(),wordList.end(),endWord);
        if(itor==wordList.end()){
            return 0;
        }else{
            //cout<<itor-wordList.begin()<<endl;
            bfs.push(int(itor-wordList.begin()));
        }
        vector<int> visited(wordList.size(),0);
        int len=0;
        int cur=0;
        int res=0;
        while(!bfs.empty()){
            cur=bfs.front();
            len=bfs.size();
            bfs.pop();
            if(visited[cur]==1){
                continue;
            }
            if(wordList[cur]==beginWord){
                return res;
            }
            res++;
            visited[cur]=1;
            while(len--){
                for(int i=0;i<wordList.size();i++){
                    if(visited[i]==0&&onediff(wordList[cur],wordList[i])){
                        bfs.push(i);
                    }
                }
            }
        }
        return res;
    }
    bool onediff(const string& a,const string& b){
        int diff=0;
        for(int i=0;i<a.size();i++){
            if(a[i]!=b[i]){
                diff++;
            }
            if(diff>1){
                return false;
            }
        }
        return diff==1;
    }
};

//更高效版本
/*
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        queue<int> bfs;
        auto itor=find(wordList.begin(),wordList.end(),endWord);
        if(itor==wordList.end()){
            return 0;
        }else{
            bfs.push(itor-wordList.begin());
            //cout<<"endword_idx:"<<itor-wordList.begin()<<endl;
        }
        vector<int> visited(wordList.size(),0);
        int len=0;
        int cur=0;
        int res=0;
        while(!bfs.empty()){
            len=bfs.size();
            res++;
            while(len--){
                cur=bfs.front();
                //cout<<"cur:"<<cur<<" word:"<<wordList[cur]<<endl;
                bfs.pop();
                if(visited[cur]==1){
                    continue;
                }
                //cout<<wordList[cur]<<" visited:"<<visited[cur]<<endl;
                if(onediff(wordList[cur],beginWord)){
                    return res+1;
                }
                visited[cur]=1;

                for(int i=0;i<wordList.size();i++){
                    if(visited[i]==0&&onediff(wordList[cur],wordList[i])){
                        bfs.push(i);
                        //cout<<"push:"<<wordList[i]<<endl;
                    }
                }
                //cout<<" "<<endl;
            }
        }
        return 0;
    }

    bool onediff(const string& a,const string& b){
        int diff=0;
        for(int i=0;i<a.size();i++){
            if(a[i]!=b[i]){
                diff++;
            }
            if(diff>1){
                return false;
            }
        }
        return diff==1;
    }
};
*/
int main(){
    Solution s;
    string begin="hit";
    string end="cog";
    vector<string> wordlist{"hot","dot","dog","lot","log","cog"};
    cout<<s.ladderLength(begin,end,wordlist)<<endl;
    return 0;
}